home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvitops / pk.c < prev    next >
C/C++ Source or Header  |  1991-01-25  |  12KB  |  524 lines

  1. static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/pk.c,v 1.7 90/10/19 09:54:55 jjc Exp $";
  2.  
  3. #include "dvitops.h"
  4.  
  5. #define pk_id 89
  6.  
  7. #if 0 
  8. enum pk_command { pk_xxx1 = 240, pk_xxx2 = 241, pk_xxx3 = 242, pk_xxx4 = 243,
  9. pk_yyy = 244, pk_post = 245, pk_no_op = 246, pk_pre = 247 };
  10. #else
  11. #define pk_xxx1  240
  12. #define pk_xxx2  241
  13. #define pk_xxx3  242
  14. #define pk_xxx4  243
  15. #define pk_yyy  244
  16. #define pk_post  245
  17. #define pk_no_op  246
  18. #define pk_pre  247
  19.  
  20. #endif
  21. static struct {
  22.     integer llx, lly, urx, ury;
  23. } bb; /* bounding box for the entire font */
  24. #ifdef PROTO
  25. static void out_byte(PROMOTED_UNSIGNED_CHAR c, FILE *psfp);
  26. static void blacken(integer start, integer n, unsigned char *buf);
  27. static integer packed_num(int dyn_f);
  28. static void bitmap_char(integer h, integer w, FILE *psfp);
  29. static integer makeinteger(unsigned char *p);
  30. static int generate_char(PROMOTED_UNSIGNED_CHAR flag, unsigned char *data,
  31.                          size_t len, FILE *psfp);
  32. #else
  33. static void out_byte();
  34. static void blacken();
  35. static integer packed_num();
  36. static void bitmap_char();
  37. static integer makeinteger();
  38. static int generate_char();
  39. #endif
  40.  
  41. static struct pk_info {
  42.     integer ds;
  43.     integer hppp;
  44.     integer vppp;
  45.     unsigned char flag[MAXCHARS];
  46.     size_t len[MAXCHARS];
  47.     unsigned char *data[MAXCHARS];
  48. } *pk_table[MAXFONTS];
  49.  
  50. static integer nbytes;
  51.  
  52. char *find_pk_file(name, mag)
  53. char *name;
  54. int mag;
  55. {
  56.     FILE *pkfp;
  57.     int i;
  58.     static char buf[10*FILENAME_MAX];
  59.     char *ptr = buf;
  60.     static char sep[2] = {AREA_LIST_SEP, '\0'};
  61.     for (i = 0; texpk[i] != '\0'; i++)
  62.         if (texpk[i] == '%') {
  63.             switch(texpk[i+1]) {
  64.             case 'f': case 'F':
  65.                 strcpy(ptr, name);
  66.                 break;
  67.             case 'd': case 'D':
  68.                 sprintf(ptr, "%d", mag);
  69.                 break;
  70.             default:
  71.                 sprintf(ptr, "%c", texpk[i+1]);
  72.             }
  73.             ++i;
  74.             ptr += strlen(ptr);
  75.         }
  76.         else
  77.             *ptr++ = texpk[i];
  78.     *ptr = '\0';
  79.     for (ptr = strtok(buf, sep); ptr != NULL; ptr = strtok((char *)NULL, sep)) {
  80.         if ((pkfp = FOPEN_RB(ptr)) != NULL) {
  81.             fclose(pkfp);
  82.             return ptr;
  83.         }
  84.     }
  85.     return NULL;
  86. }
  87.  
  88.  
  89. int load_pk_font(f, name, used, at_size, checksum, width, rounded_width)
  90. int f;
  91. char *name, *used;
  92. integer at_size, checksum, *width, *rounded_width;
  93. {
  94.     FILE *pkfp;
  95.     integer n;
  96.     integer cs;
  97.     double sppp;
  98.     int i;
  99.     if ((pkfp = FOPEN_RB(name)) == NULL) {
  100.         message(ERROR, 
  101.             "can't find pk file for %s: using white space instead",    name);
  102.         return 0;
  103.     }
  104. #ifdef HAVE_SETVBUF
  105.     setvbuf(pkfp, (char *)NULL, _IOFBF, 8192);
  106. #endif
  107.     if ((pk_table[f] = (struct pk_info *)
  108.                         calloc(1, sizeof(struct pk_info))) == NULL)
  109.         out_of_memory();
  110.     if (uread1(pkfp) != pk_pre)
  111.         goto bad;
  112.     if (uread1(pkfp) != pk_id)
  113.         goto bad;
  114.     n = uread1(pkfp);
  115.     fseek(pkfp, n, 1);
  116.     pk_table[f]->ds = sread4(pkfp);
  117.     cs = sread4(pkfp);
  118.     pk_table[f]->hppp = sread4(pkfp);
  119.     pk_table[f]->vppp = sread4(pkfp);
  120.     /* sppp = scaled points per pixel
  121.         sppp*dx = width in scaled points */
  122.     sppp = (double)at_size*1048576.0*65536.0
  123.                 /((double)pk_table[f]->ds*(double)pk_table[f]->hppp);
  124.  
  125.     if (cs != checksum)
  126.         message(WARNING, "%s: checksums don't match\n", name);
  127.     for (;;) {
  128.         unsigned char command = uread1(pkfp);
  129.         if (feof(pkfp) || ferror(pkfp))
  130.             goto bad;
  131.         if (((unsigned)command >> 4) == 15) {
  132.             switch (command) {
  133.             case pk_xxx1 :
  134.                 n = uread1(pkfp); break;
  135.             case pk_xxx2 :
  136.                 n = uread2(pkfp); break;
  137.             case pk_xxx3 :
  138.                 n = uread3(pkfp); break;
  139.             case pk_xxx4 :
  140.                 n = sread4(pkfp); break;
  141.             case pk_yyy  :
  142.                 (void) sread4(pkfp); break;
  143.             case pk_post :
  144.                 for (i = 0; i < MAXCHARS; i++)
  145.                     if (used[i] && width[i] == (integer) LONG_MAX)
  146.                         goto bad;
  147.                 fclose(pkfp);
  148.                 return 1;
  149.             case pk_no_op :
  150.                 break;
  151.             default:
  152.                 goto bad;
  153.             }
  154.             if (pk_xxx1 <= command && command <= pk_xxx4)
  155.                 fseek(pkfp, n, 1);
  156.         }
  157.         else {
  158.             integer cc, pl;
  159.             integer tfm;
  160.             double dx;
  161.             unsigned char c;
  162.             size_t len;
  163.             unsigned char flag = command;
  164.             command &= 0x07;
  165.             if (command == 0x07) {
  166.                 pl = sread4(pkfp);
  167.                 cc = sread4(pkfp);
  168.                 tfm = sread4(pkfp);
  169.                 dx = (double)sread4(pkfp)/65536.0;
  170.                 fseek(pkfp, -4L, 1);
  171.                 pl -= 4;
  172.             }
  173.             else if (command & 0x04) {
  174.                 pl = uread2(pkfp);
  175.                 pl |= (integer)(command & 0x03) << 16;
  176.                 cc = uread1(pkfp);
  177.                 tfm = uread3(pkfp);
  178.                 dx = (double)uread2(pkfp);
  179.                 fseek(pkfp, -2L, 1);
  180.                 pl -= 3;
  181.             }
  182.             else {
  183.                 pl = uread1(pkfp);
  184.                 pl |= (command & 0x03) << 8;
  185.                 cc = uread1(pkfp);
  186.                 tfm = uread3(pkfp);
  187.                 dx = (double)uread1(pkfp);
  188.                 fseek(pkfp, -1L, 1);
  189.                 pl -= 3;
  190.             }
  191.             if (cc < 0 || cc >= MAXCHARS) {
  192.                 fseek(pkfp, pl, SEEK_CUR);
  193.                 continue;
  194.             }
  195.             c = (unsigned char)cc;
  196.             if (!used[c]) {
  197.                 pk_table[f]->data[c] = NULL;
  198.                 fseek(pkfp, pl, SEEK_CUR);
  199.             }
  200.             else {
  201.                 if (pl < 0 || pl > SIZE_MAX)
  202.                     goto bad;
  203.                 len = (size_t)pl;
  204.                 width[c] = scale(tfm, at_size);
  205.                 rounded_width[c] = (integer)(dx*sppp);
  206.                 pk_table[f]->flag[c] = flag;
  207.                 pk_table[f]->len[c] = len;
  208.                 if ((pk_table[f]->data[c] = (unsigned char *)malloc(len))
  209.                                 == NULL)
  210.                     out_of_memory();
  211.                 if (fread((char *)pk_table[f]->data[c], 1, len, pkfp) != len)
  212.                     goto bad;
  213.             }
  214.         }
  215.     }
  216.     /* can't get here */
  217. bad:
  218.     message(ERROR, "%s: bad pk file: using white space instead", name);
  219.     return 0;
  220. }
  221.  
  222. static unsigned char *ptr;
  223. static char biti;
  224. static integer rc;
  225.  
  226. #define get_nyb() (biti == 0 ? (biti=4, (unsigned)*ptr>>4) \
  227. : (biti = 0, *ptr++ & 0x0f))
  228.  
  229.  
  230. static integer packed_num(dyn_f)
  231. int dyn_f;
  232. {
  233.     integer i, j;
  234.     integer n;
  235.     i = get_nyb();
  236.     if (i == 0) {
  237.         do {
  238.              j = get_nyb();
  239.              i++;
  240.         } while (j == 0);
  241.         while (i > 0) {
  242.              j = (j << 4) + get_nyb();
  243.              i--;
  244.         }
  245.         n = (j - 15 + ((13 - dyn_f) << 4) + dyn_f);
  246.     }
  247.     else if (i <= dyn_f)
  248.         n = i;
  249.     else if (i < 14)
  250.         n = ((i - dyn_f - 1) << 4) + get_nyb() + dyn_f + 1;
  251.     else {
  252.         rc = i == 14 ? packed_num(dyn_f) : 1;
  253.         n = packed_num(dyn_f);
  254.     }
  255.     return n;
  256. }
  257.  
  258. /* this can be made a lot more efficient later */
  259.  
  260. static void blacken(start, n, buf)
  261. integer start, n;
  262. unsigned char *buf;
  263. {
  264.     integer i;
  265.     for (i = start; i < start + n; i++)
  266.         buf[(size_t)(i/8)] |= (unsigned)128 >> (int)(i & 7);
  267. }
  268.  
  269.  
  270. static char *hex = "0123456789ABCDEF";
  271.  
  272. static void out_byte(c, psfp)
  273. unsigned char c;
  274. FILE *psfp;
  275. {
  276.     static int cols = 0;
  277.     putc(hex[(unsigned)(c) >> 4],psfp);
  278.     putc(hex[(c) & 15],psfp);
  279.     if ((cols += 2) > 70) {
  280.         cols = 0;
  281.         putc('\n', psfp);
  282.     }
  283.     ++nbytes;
  284. }
  285.  
  286. /* postscript requires that the bitmap of each row be padded out to an
  287. integral number of bytes, so unfortunately we can't just copy the bitmap
  288. in the pk file; this function could probably be made faster, but most
  289. of the characters that pk format represents by bitmaps are fairly small */
  290.  
  291. static void bitmap_char(h, w, psfp)
  292. integer h, w;
  293. FILE *psfp;
  294. {
  295.     integer i, j;
  296.     unsigned mask = 0x80;
  297.     unsigned char curbyte = 0;
  298.     unsigned curmask = 0x80;
  299.     for (i = 0; i < h; i++)
  300.         for (j = 0; j < w; j++) {
  301.             if (*ptr & mask)
  302.                 curbyte |= curmask;
  303.             if ((mask >>= 1) == 0) {
  304.                 mask = 0x80;
  305.                 ptr++;
  306.             }
  307.             if ((curmask >>= 1) == 0 || j == w - 1) {
  308.                 out_byte(curbyte, psfp);
  309.                 curbyte = 0;
  310.                 curmask = 0x80;
  311.             }
  312.         }
  313. /* the value of ptr is checked on return to make sure we have used the right
  314. number of bytes */
  315.     if (mask != 0x80) 
  316.         ptr++;
  317. }
  318.  
  319. static integer makeinteger(p)
  320. unsigned char *p;
  321. {
  322.     return (((integer)p[0]<<24) | ((integer)p[1]<<16) | (p[2]<<8) | p[3]);
  323. }
  324.  
  325. /*
  326. output strings have one of the following forms:
  327. (4 byte integers are always signed)
  328. flag[1] dm[1] w[1] h[1] hoff[+1] voff[+1] flag = 0
  329. flag[1] dm[2] w[2] h[2] hoff[+2] voff[+2] flag = 1
  330. flag[1] dx[4] dy[4] w[4] h[4] hoff[4] voff[4] flag = 2
  331. */
  332.  
  333. /* returns 0 on error != 0 otherwise */
  334. static int generate_char(flag, data, len, psfp)
  335. unsigned char flag;
  336. unsigned char *data;
  337. size_t len;
  338. FILE *psfp;
  339. {
  340.     int black = (flag & 0x08) != 0;
  341.     integer h, w;
  342.     int dyn_f;
  343.     integer hoff, voff;
  344.     integer curcol, currow;
  345.     unsigned char *rowbuf;
  346.     size_t buflen;
  347.     dyn_f = (unsigned)flag >> 4;
  348.     ptr = data;
  349.     rc = 0;
  350.     biti = 0;
  351.     fputc('<',psfp);
  352.     if ((flag & 0x07) == 0x07) {
  353.         int i;
  354.         out_byte(2, psfp);
  355.         for (i = 0; i < 24; i++)
  356.             out_byte(ptr[i], psfp);
  357.         ptr += 8;
  358.         w = makeinteger(ptr); ptr += 4;
  359.         h = makeinteger(ptr); ptr += 4;
  360.         hoff = makeinteger(ptr); ptr += 4;
  361.         voff = makeinteger(ptr); ptr += 4;
  362.     }
  363.     else if (flag & 0x04) {
  364.         int i;
  365.         out_byte(1, psfp);
  366.         for (i = 0; i < 10; i++)
  367.             out_byte(ptr[i], psfp);
  368.         ptr += 2;
  369.         w = (ptr[0] << 8) | ptr[1]; ptr += 2;
  370.         h = (ptr[0] << 8) | ptr[1]; ptr += 2;
  371.         hoff = *ptr++;
  372.         if (hoff >= 128)
  373.             hoff -= 256;
  374.         hoff <<= 8;
  375.         hoff |= *ptr++;
  376.         voff = *ptr++;
  377.         if (voff >= 128)
  378.             voff -= 256;
  379.         voff <<= 8;
  380.         voff |= *ptr++;
  381.     }
  382.     else {
  383.         int i;
  384.         out_byte(0, psfp);
  385.         for (i = 0; i < 5; i++)
  386.             out_byte(ptr[i], psfp);
  387.         ptr++;
  388.         w = *ptr++;
  389.         h = *ptr++;
  390.         hoff = *ptr++;
  391.         if (hoff >= 128)
  392.             hoff -= 256;
  393.         voff = *ptr++;
  394.         if (voff >= 128)
  395.             voff -= 256;
  396.     }
  397.     if (-hoff < bb.llx)
  398.         bb.llx = -hoff;
  399.     if (w-hoff > bb.urx)
  400.         bb.urx = w-hoff;
  401.     if (voff + 1 - h < bb.lly)
  402.         bb.lly = voff + 1 - h;
  403.     if (voff + 1 > bb.ury)
  404.         bb.ury = voff + 1;
  405.     if (dyn_f == 14) {
  406.         bitmap_char(h, w, psfp);
  407.         if (data + len != ptr)
  408.             return 0;
  409.         fputc('>',psfp);
  410.         return 1;
  411.     }
  412.     currow = curcol = 0;
  413.     buflen = (size_t)((w + 7) / 8);
  414.     if (buflen == SIZE_MAX) /* we'd get an infinite loop if we allowed this */
  415.         return 0;
  416.     rowbuf = (unsigned char *)calloc(1, buflen);
  417.     if (rowbuf == NULL)
  418.         out_of_memory();
  419.     while  (currow < h) {
  420.         integer run = packed_num(dyn_f);
  421.         while (curcol + run >= w) {
  422.             size_t i;
  423.             integer j;
  424.             if (black)
  425.                 blacken(curcol, w - curcol, rowbuf);
  426.             for (j = 0; j <= rc; j++) {
  427.                 for (i = 0; i < buflen; i++)
  428.                     out_byte(rowbuf[i],psfp);
  429.             }
  430.             for (i = 0; i < buflen; i++)
  431.                 rowbuf[i] = 0;
  432.             currow++; currow += rc; rc = 0;
  433.             run -= w - curcol;
  434.             curcol = 0;
  435.         }
  436.         if (black)
  437.             blacken(curcol, run, rowbuf);
  438.         curcol += run;
  439.         black = !black;
  440.     }
  441.     if (biti > 0)
  442.         ptr++;
  443.     if (data + len != ptr)
  444.         return 0;
  445.     fputc('>',psfp);
  446.     free((char *)rowbuf);
  447.     return 1;
  448. }
  449.  
  450.     
  451. integer emit_pk_font(f, name, used, psfp)
  452. int f;
  453. char *name;
  454. char *used;
  455. FILE *psfp;
  456. {
  457.     int i, nused;
  458.     nbytes = 0;
  459.     if (pk_table[f] == NULL)
  460.         cant_happen();
  461.     fprintf(psfp, "%%%%BeginFont: %s\n", name);
  462.     fprintf(psfp, "/%s %ld %ld %ld\n", name, (long)(pk_table[f]->ds),
  463.             (long)(pk_table[f]->hppp), (long)(pk_table[f]->vppp));
  464.     bb.llx = bb.lly = bb.urx = bb.ury = 0;
  465.     nused = 0;
  466.     fputs("EmptyEncoding 256 array copy\n", psfp);
  467.     for (i = 0; i < MAXCHARS; i++)
  468.         if (used[i]) {
  469.             fprintf(psfp, "dup %d /c%d put\n", i, i);
  470.             ++nused;
  471.         }
  472.     /* allow room for /.notdef */
  473.     fprintf(psfp, "\n%d dict dup begin\n", nused+1);
  474.     for (i = 0; i < MAXCHARS; i++)
  475.         if (used[i]) {
  476.             if (pk_table[f]->data[i] == NULL)
  477.                 cant_happen();
  478.             fprintf(psfp, "/c%d", i);
  479.             if (!generate_char(pk_table[f]->flag[i], pk_table[f]->data[i],
  480.                     pk_table[f]->len[i], psfp))
  481.                 message(FATAL_ERROR, 
  482.                     "char %d in the .pk file for %s is bad: use pktype",
  483.                     i, name);
  484.             fputs("def\n", psfp);
  485.         }
  486.     fprintf(psfp, "end %ld %ld %ld %ld DefinePKFont\n", (long)(bb.llx),
  487.         (long)(bb.lly), (long)(bb.urx), (long)(bb.ury));
  488.     fputs("%%EndFont\n", psfp);
  489.     /* this is a fairly good estimate of the overhead for each font */
  490.     return nbytes + 1024 + 2000 + 20*(nused+1); 
  491.     /* nbytes for the strings, 1024 for the encoding vector,
  492.         20 for each of the nused+1 entries in the dictionary
  493.         plus 2000 for general overhead */
  494. }
  495.  
  496.  
  497.  
  498.  
  499. void free_pk_font(n)
  500. int n;
  501. {
  502.     int i;
  503.     struct pk_info *p = pk_table[n];
  504.     if (pk_table[n] == NULL)
  505.         cant_happen();
  506.     for (i = 0; i < MAXCHARS; i++)
  507.         if (p->data[i] != NULL)
  508.             free((char *)(p->data[i]));
  509.     free((char *)p);
  510.     pk_table[n] = NULL;
  511. }
  512.  
  513. /*
  514. Local Variables:
  515. c-indent-level: 4
  516. c-continued-statement-offset: 4
  517. c-brace-offset: -4
  518. c-argdecl-indent: 0
  519. c-label-offset: -4
  520. tab-width: 4
  521. End:
  522. */
  523.  
  524.